package biz.karms.sinkit.rest;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.logging.Level;
import java.util.logging.Logger;
import static biz.karms.sinkit.ejb.protostream.CustomlistProtostreamGenerator.GENERATED_PROTOFILES_DIRECTORY;
import static biz.karms.sinkit.ejb.protostream.CustomlistProtostreamGenerator.SINKIT_CUSTOMLIST_PROTOSTREAM_GENERATOR_D_H_M_S;
import static biz.karms.sinkit.ejb.protostream.CustomlistProtostreamGenerator.customListFileMd5;
import static biz.karms.sinkit.ejb.protostream.CustomlistProtostreamGenerator.customListFilePath;
import static biz.karms.sinkit.ejb.protostream.IocProtostreamGenerator.SINKIT_IOC_PROTOSTREAM_GENERATOR_D_H_M_S;
import static biz.karms.sinkit.ejb.protostream.IocProtostreamGenerator.iocListFileMd5;
import static biz.karms.sinkit.ejb.protostream.IocProtostreamGenerator.iocListFilePath;
import static biz.karms.sinkit.ejb.protostream.WhitelistProtostreamGenerator.SINKIT_WHITELIST_PROTOSTREAM_GENERATOR_D_H_M_S;
import static biz.karms.sinkit.ejb.protostream.WhitelistProtostreamGenerator.whiteListFileMd5;
import static biz.karms.sinkit.ejb.protostream.WhitelistProtostreamGenerator.whiteListFilePath;
import static biz.karms.sinkit.rest.DnsREST.CLIENT_ID_HEADER_PARAM;
/**
* @author Michal Karm Babacek
*/
@RequestScoped
@Path("/")
public class ProtostreamREST implements Serializable {
private static final long serialVersionUID = -811275040019884876L;
@Inject
SinkitService sinkitService;
@Inject
private Logger log;
public static final int TRY_LATER = 466;
public static final String X_ERROR = "X-error";
public static final String X_FILE_LENGTH = "X-file-length";
public static final String X_FILE_MD5 = "X-file-md5";
/**
* @returns huge byte array Protocol Buffer with Whitelist records
*/
@GET
@Path("/protostream/whitelist")
@Produces({"application/x-protobuf"})
public Response getProtostreamWhitelist() {
if (SINKIT_WHITELIST_PROTOSTREAM_GENERATOR_D_H_M_S == null) {
return Response.status(Response.Status.NOT_FOUND).header(X_ERROR, "This is a wrong node. Protostream generator is not started.").build();
}
final File whiteListBinary = new File(whiteListFilePath);
final File whitelistBinaryMD5 = new File(whiteListFileMd5);
if (whiteListBinary.exists() && whitelistBinaryMD5.exists()) {
InputStream is;
String md5sum;
try {
is = new FileInputStream(whiteListBinary);
md5sum = new String(Files.readAllBytes(whitelistBinaryMD5.toPath()), StandardCharsets.UTF_8);
} catch (FileNotFoundException e) {
log.log(Level.SEVERE, whiteListFilePath + " not found.");
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).header(X_ERROR, whiteListFilePath + " not found.").build();
} catch (IOException e) {
log.log(Level.SEVERE, whiteListFileMd5 + " not found.");
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).header(X_ERROR, whiteListFileMd5 + " not found.").build();
}
return Response.ok().entity(is)
.header(X_FILE_LENGTH, String.valueOf(whiteListBinary.length()))
.header(X_FILE_MD5, md5sum)
.build();
} else {
return Response.status(TRY_LATER).header(X_ERROR, "Try later, please.").build();
}
}
/**
* @returns huge byte array Protocol Buffer with custom list records
*/
@GET
@Path("/protostream/customlist")
@Produces({"application/x-protobuf"})
public Response getProtostreamCustomList(@HeaderParam(CLIENT_ID_HEADER_PARAM) Integer clientId) {
if (SINKIT_CUSTOMLIST_PROTOSTREAM_GENERATOR_D_H_M_S == null) {
return Response.status(Response.Status.NOT_FOUND).header(X_ERROR, "This is a wrong node. Protostream generator is not started.").build();
}
if (clientId == null || clientId < 0) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).header(X_ERROR, CLIENT_ID_HEADER_PARAM + " seems to be invalid or missing").build();
}
final File customListBinary = new File(customListFilePath + clientId);
final File customlistBinaryMD5 = new File(customListFileMd5 + clientId);
if (customListBinary.exists() && customlistBinaryMD5.exists()) {
InputStream is;
String md5sum;
try {
is = new FileInputStream(customListBinary);
md5sum = new String(Files.readAllBytes(customlistBinaryMD5.toPath()), StandardCharsets.UTF_8);
} catch (FileNotFoundException e) {
log.log(Level.SEVERE, customListFilePath + clientId + " not found.");
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).header(X_ERROR, customListFilePath + clientId + " not found.").build();
} catch (IOException e) {
log.log(Level.SEVERE, customListFileMd5 + clientId + " not found.");
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).header(X_ERROR, customListFileMd5 + clientId + " not found.").build();
}
return Response.ok().entity(is)
.header(X_FILE_LENGTH, String.valueOf(customListBinary.length()))
.header(X_FILE_MD5, md5sum)
.build();
} else {
// If any other file is generated, it means the generator cycle already passed, but there are no data for this particular client ID
try (DirectoryStream<java.nio.file.Path> someFiles = Files.newDirectoryStream(Paths.get(GENERATED_PROTOFILES_DIRECTORY), "ioclist.bin*")) {
if (someFiles.iterator().hasNext()) {
customListBinary.createNewFile();
// The desired behaviour is to return an empty file
return Response.ok().entity(new FileInputStream(customListBinary))
.header(X_FILE_LENGTH, "0")
.header(X_FILE_MD5, "")
.build();
}
} catch (IOException e) {
return Response.status(TRY_LATER).header(X_ERROR, "Try later, please.").build();
}
return Response.status(TRY_LATER).header(X_ERROR, "Try later, please.").build();
}
}
/**
* @returns huge byte array Protocol Buffer with custom list records
*/
@GET
@Path("/protostream/ioclist")
@Produces({"application/x-protobuf"})
public Response getProtostreamIOCList(@HeaderParam(CLIENT_ID_HEADER_PARAM) Integer clientId) {
if (SINKIT_IOC_PROTOSTREAM_GENERATOR_D_H_M_S == null) {
return Response.status(Response.Status.NOT_FOUND).header(X_ERROR, "This is a wrong node. Protostream generator is not started.").build();
}
if (clientId == null || clientId < 0) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).header(X_ERROR, CLIENT_ID_HEADER_PARAM + " seems to be invalid or missing").build();
}
final File iocListBinary = new File(iocListFilePath + clientId);
final File customlistBinaryMD5 = new File(iocListFileMd5 + clientId);
if (iocListBinary.exists() && customlistBinaryMD5.exists()) {
InputStream is;
String md5sum;
try {
is = new FileInputStream(iocListBinary);
md5sum = new String(Files.readAllBytes(customlistBinaryMD5.toPath()), StandardCharsets.UTF_8);
} catch (FileNotFoundException e) {
log.log(Level.SEVERE, iocListFilePath + clientId + " not found.");
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).header(X_ERROR, iocListFilePath + clientId + " not found.").build();
} catch (IOException e) {
log.log(Level.SEVERE, iocListFileMd5 + clientId + " not found.");
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).header(X_ERROR, iocListFileMd5 + clientId + " not found.").build();
}
return Response.ok().entity(is)
.header(X_FILE_LENGTH, String.valueOf(iocListBinary.length()))
.header(X_FILE_MD5, md5sum)
.build();
} else {
// If any other file is generated, it means the generator cycle already passed, but there are no data for this particular client ID
try (DirectoryStream<java.nio.file.Path> someFiles = Files.newDirectoryStream(Paths.get(GENERATED_PROTOFILES_DIRECTORY), "ioclist.bin*")) {
if (someFiles.iterator().hasNext()) {
iocListBinary.createNewFile();
// The desired behaviour is to return an empty file
return Response.ok().entity(new FileInputStream(iocListBinary))
.header(X_FILE_LENGTH, "0")
.header(X_FILE_MD5, "")
.build();
}
} catch (IOException e) {
return Response.status(TRY_LATER).header(X_ERROR, "Try later, please.").build();
}
return Response.status(TRY_LATER).header(X_ERROR, "Try later, please.").build();
}
}
}